package gek.uni.aspirant.ocl.rcp.command.handlers;

import gek.uni.aspirant.ocl.parser.mptree.tree.INode;
import gek.uni.aspirant.ocl.parser.mptree.tree.RootNode;
import gek.uni.aspirant.ocl.parser.mptree.tree.VariableNode;
import gek.uni.aspirant.ocl.parser.ocl2tree.parser.OclToMPTreeParser;

import java.util.Set;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;

/**
 * @deprecated Не нужный класс, в будущем удалить
 * @author Gek
 *
 * TODO удалить класс
 */
@Deprecated
public class Ocl2MPTreeHandler extends AbstractHandler implements IHandler {

  @Override
  public Object execute(ExecutionEvent event) throws ExecutionException {
    OclToMPTreeParser parser = new OclToMPTreeParser();

    // String expression =
    // "self.children->select(ch | ch.oclIsUndefined())->size()>2 and self.children->isEmpty() and self.children->size()=2 and self.size>3";
    String expression = "self.children->isEmpty() or self.size>3";
    System.out.println("Source expression = \n\t" + expression);

    parser.setStringToParse(expression);
    RootNode result = null;
    try {
      result = (RootNode) parser.parse();
    } catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println("MP-Tree = \n\t" + result.toString());

    String variableDefCode = generateVariableDefString(result, null);
    System.out.println("Variable defenition Prolog-code = \n\t"
        + variableDefCode);
    return null;
  }

  /**
   * Создает код объявления необходимых переменных на языке Prolog
   * 
   * @param node
   * @param stringBuilder
   * @return
   */
  public String generateVariableDefString(RootNode node,
      StringBuilder stringBuilder) {
    if (stringBuilder == null)
      stringBuilder = new StringBuilder();
    for (INode child : node.getChildren()) {
      generateVariableDeclarations((VariableNode) child, stringBuilder);
      stringBuilder.append(",");
    }
    int length = stringBuilder.length();
    if (length > 0)
      stringBuilder.deleteCharAt(length - 1);
    stringBuilder.append(".");
    return stringBuilder.toString();
  }

  /**
   * Генерирует код объявления переменной, представленной узлом node
   * 
   * @param node
   * @param stringBuilder
   * @return
   */

  public String generateVariableDeclarations(VariableNode node,
      StringBuilder stringBuilder) {
    if (stringBuilder == null)
      stringBuilder = new StringBuilder();

    Set<INode> nodeChildren = node.getChildren();

    String varName = node.getName();
    String className = node.getValueClassName();
    String shortClassName = getLastSegment(className);

    if (isPrimitiveClass(className))
      stringBuilder.append(shortClassName.toLowerCase()).append("(").append(
          varName).append(")");
    else {
      stringBuilder.append(varName).append("=").append(
          shortClassName.toLowerCase()).append("(");
      for (INode obj : nodeChildren) {
        VariableNode child = (VariableNode) obj;

        String childVarName = child.getName();
        String childOriginalName = child.getOriginalName();
        stringBuilder.append(childOriginalName).append("-")
            .append(childVarName);
        stringBuilder.append(",");
      }
      if (nodeChildren.size() > 0)
        stringBuilder.deleteCharAt(stringBuilder.length() - 1);
      stringBuilder.append(")");
    }
    for (INode child : node.getChildren()) {
      stringBuilder.append(",");
      generateVariableDeclarations((VariableNode) child, stringBuilder);
    }
    return stringBuilder.toString();
  }

  /**
   * 
   * @param className
   * @return true, если className - имя примитивного класса
   */
  private boolean isPrimitiveClass(String className) {
    if (Integer.class.getName().equals(className))
      return true;
    if (className.startsWith("java"))
      return true;

    return false;
  }

  /**
   * 
   * @param dotSeparatedString
   * @return возвращает последний сегмент строки dosSeparatedString разделенной
   *         точками
   */
  public String getLastSegment(String dotSeparatedString) {
    StringBuilder bldr = new StringBuilder();
    String[] splits = dotSeparatedString.split("\\.");
    if (splits.length > 0)
      bldr.append(splits[splits.length - 1]);
    return bldr.toString();
  }
}
